package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"
)

func page_Index(res http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(res, "Hello world, 爱看书的小沐的家！")
}

func HttpServerStart(server *http.Server) {
	//启动服务器监听;
	erro1 := server.ListenAndServe()
	if erro1 != nil && erro1 != http.ErrServerClosed {
		fmt.Printf("Http服务器%s启动失败:%v\n", server.Addr, erro1)
		log.Fatal(erro1)
	}
}

func InputScan(input chan string) {
	var inputString string
	fmt.Scanln(&inputString)
	input <- inputString
}

func main() {
	fmt.Println("Hello Golang HttpServer")

	var Port int64 = 8080
	fmt.Println("默认监听端口:", Port, "请输入自定义端口，无需输入直接回车")
	_, erro0 := fmt.Scanln(&Port)
	if erro0 != nil {
		fmt.Println("输入端口为空，或者未输入内容，将使用默认端口开启服务器")
	}

	addr := "localhost:" + strconv.FormatInt(Port, 10)
	fmt.Println("开启服务器地址为:", addr)

	//启动服务器;
	mx := http.NewServeMux()

	//设置首页调用函数;
	mx.HandleFunc("/", page_Index) // page_Index 为向 url发送请求时，调用的函数;

	server := http.Server{
		Addr:    addr,
		Handler: mx,
	}

	go HttpServerStart(&server)

	//设置退出信号;
	signalCh := make(chan os.Signal, 1)
	signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)

	// 创建一个通道来接收用户输入
	input := make(chan string, 1)

	fmt.Println("输出exit关闭服务器")

WaitBreak:
	for {
		//监控输入;
		go InputScan(input)
		// 同时选择处理输入或信号
		select {
		case s := <-signalCh:
			fmt.Println() // 打印换行，以便终止信号提示可见
			fmt.Printf("程序接收到信号：%s\n", s)
			break WaitBreak
		case i := <-input:
			fmt.Printf("用户输入：%s\n", i)
			if i == "exit" {
				break WaitBreak
			}
		}

	}
	fmt.Println("开始退出流程")

	ctxTimeout, cancelTimeout := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancelTimeout()

	if err := server.Shutdown(ctxTimeout); err != nil {
		select {
		case <-ctxTimeout.Done():
			// 由于达到超时时间服务器关闭，未完成优雅关闭
			fmt.Println("timeout of 5 seconds.")
		default:
			// 其他原因导致的服务关闭异常，未完成优雅关闭
			fmt.Println("退出Server failed:", err)
		}
		return
	}

	// 正确执行优雅关闭服务器
	fmt.Println("退出Server")
}
